/**
 * Copyright 2006 Brad Reynolds
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.leeloo.databinding.ui.event;

import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.databinding.BindingEvent;
import org.leeloo.databinding.internal.ui.Databinding;
import org.leeloo.databinding.internal.ui.LabeledTreeNode;
import org.leeloo.databinding.internal.ui.LabeledTreeNodeBuilder;
import org.leeloo.databinding.ui.descriptor.BindingEventDescriptor;
import org.leeloo.databinding.ui.descriptor.ObservableDescriptor;
import org.leeloo.internal.core.ObjectDescriptor;

/**
 * Represents the firing of a {@link BindingEvent}.
 * 
 * @author Brad Reynolds
 */
public class FireBindingEventEvent extends AbstractEvent implements IAdaptable {
    private static final String TYPE_DISPLAY = Messages.getString("FireBindingEventEvent.binding_event_display"); //$NON-NLS-1$

    private ObjectDescriptor bindingDescriptor;

    private BindingEventDescriptor bindingEventDescriptor;
    
    public FireBindingEventEvent() {
    }

    public ObjectDescriptor getBindingDescriptor() {
        return bindingDescriptor;
    }

    public BindingEventDescriptor getBindingEventDescriptor() {
        return bindingEventDescriptor;
    }

    public String getTypeDisplay() {
        return TYPE_DISPLAY;
    }

    private String display;

    public String getDisplay() {
        if (display == null) {
            StringBuffer buffer = new StringBuffer();

            buffer.append(Databinding.getBindingEventName(bindingEventDescriptor.getCopyType()))
                    .append(Messages.getString("FireBindingEventEvent.separator")) //$NON-NLS-1$
                    .append(Databinding.getPipelinePositionName(bindingEventDescriptor.getPipelinePosition()))
                    .append(Messages.getString("FireBindingEventEvent.separator")) //$NON-NLS-1$
                    .append(Messages.getString("FireBindingEventEvent.begin_diff")); //$NON-NLS-1$

            if (bindingEventDescriptor.getDiffDescriptor() != null) {
                buffer.append(bindingEventDescriptor.getDiffDescriptor().getCleanToString());
            } else {
                buffer.append(Messages.getString("FireBindingEventEvent.null")); //$NON-NLS-1$
            }
            buffer.append(Messages.getString("FireBindingEventEvent.end_diff")); //$NON-NLS-1$

            display = buffer.toString();
        }

        return display;
    }

    /**
     * @param bindingDescriptor
     *            the bindingDescriptor to set
     */
    public void setBindingDescriptor(ObjectDescriptor bindingDescriptor) {
        this.bindingDescriptor = bindingDescriptor;
    }

    /**
     * @param bindingEventDescriptor
     *            the bindingEventDescriptor to set
     */
    public void setBindingEventDescriptor(BindingEventDescriptor bindingEventDescriptor) {
        this.bindingEventDescriptor = bindingEventDescriptor;
    }

    public Object getAdapter(Class adapter) {
        Object result = null;
        if (LabeledTreeNode.class.equals(adapter)) {
            LabeledTreeNode thisNode = new LabeledTreeNode(this);
            thisNode.setLabel(Messages.getString("FireBindingEventEvent.event_name")); //$NON-NLS-1$

            LabeledTreeNodeBuilder builder = LabeledTreeNodeBuilder.forNode(thisNode);
            builder.addChild(bindingDescriptor, Messages.getString("FireBindingEventEvent.binding")); //$NON-NLS-1$
            builder.addChild(bindingEventDescriptor, Messages.getString("FireBindingEventEvent.binding_event")); //$NON-NLS-1$
            result = builder.build();
        }

        return result;
    }

    private static final ObjectDescriptor[] NO_OBJECT_DESCRIPTORS = new ObjectDescriptor[0];

    /**
     * @return object descriptos that are part of the event.
     */
    public ObjectDescriptor[] getParticipants() {
        List participants = new LinkedList();

        if (bindingDescriptor != null) {
            participants.add(bindingDescriptor);
        }

        if (bindingEventDescriptor != null) {
            participants.add(bindingEventDescriptor);
            if (bindingEventDescriptor.getDiffDescriptor() != null) {
                participants.add(bindingEventDescriptor.getDiffDescriptor());
            }
            if (bindingEventDescriptor.getTargetObservableDescriptor() != null) {
                ObservableDescriptor target = bindingEventDescriptor.getTargetObservableDescriptor();

                participants.add(target);
                if (target.getObservedDescriptor() != null) {
                    participants.add(target.getObservedDescriptor());
                }
            }

            if (bindingEventDescriptor.getModelObservableDescriptor() != null) {
                ObservableDescriptor model = bindingEventDescriptor.getModelObservableDescriptor();

                participants.add(model);
                if (model.getObservedDescriptor() != null) {
                    participants.add(model.getObservedDescriptor());
                }
            }
        }

        return (participants.size() > 0) ? (ObjectDescriptor[]) participants.toArray(new ObjectDescriptor[participants.size()])
                : NO_OBJECT_DESCRIPTORS;
    }
}